package com.tt.vtg.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.tt.vtg.dao.entity.Role;
import com.tt.vtg.exception.ExceptionConstants;
import com.tt.vtg.exception.VtgException;
import com.tt.vtg.plain.info.RoleInfo;
import com.tt.vtg.service.RoleService;

@RestController
public class RoleManagementController {

	@Autowired
	@Qualifier("roleSvc")
	private RoleService roleSvc;

	@RequestMapping(value = "/role", method = RequestMethod.POST)
	@ResponseStatus(value = HttpStatus.CREATED)
	public long createRole(@RequestBody @Validated RoleInfo roleInfo) {

		// check whether the role is exist.
		checkRoleExist(roleInfo);

		Role role = packageRole(roleInfo);
		roleSvc.save(role);

		return role.getId();
	}

	@RequestMapping(value = "/role/{roleId}", method = RequestMethod.GET)
	public RoleInfo getRole(@PathVariable("roleId") String roleId) {
		Role role = getRoleById(roleId);
		return new RoleInfo(role);
	}

	@RequestMapping(value = "/roles", method = RequestMethod.GET)
	public List<RoleInfo> getRoles() {
		List<Role> roles = roleSvc.getAll();

		List<RoleInfo> roleInfos = roles.stream().map(u -> new RoleInfo(u))
				.collect(Collectors.toCollection(ArrayList::new));

		return roleInfos;
	}

	@RequestMapping(value = "/role/{roleId}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void deleteRole(@PathVariable("roleId") String roleId) {
		Role role = getRoleById(roleId);
		roleSvc.delete(role.getId());
	}

	@RequestMapping(value = "/role/{roleId}", method = RequestMethod.PUT)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void updateRole(@RequestBody @Validated RoleInfo roleInfo, @PathVariable("roleId") String roleId) {

		Role role = getRoleById(roleId);
		role.setRoleName(roleInfo.getRoleName());

		roleSvc.update(role);
	}

	private Role packageRole(RoleInfo roleInfo) {
		Role role = new Role();
		role.setRoleId(roleInfo.getRoleId());
		role.setRoleName(roleInfo.getRoleName());
		return role;
	}

	private Role checkRoleExist(RoleInfo roleInfo) {
		Role role = getRoleById(roleInfo.getRoleId(), false);
		if (role != null) {
			throw new VtgException(HttpServletResponse.SC_BAD_REQUEST, ExceptionConstants.OTHER_ERROR,
					"Role[" + roleInfo.getRoleId() + "] has existed.");
		}

		return role;
	}

	private Role getRoleById(String roleId) {
		return getRoleById(roleId, true);
	}

	private Role getRoleById(String roleId, boolean isCheckNull) {
		Role role = roleSvc.getById(roleId);

		if (isCheckNull && role == null) {
			throw new VtgException(HttpServletResponse.SC_NOT_FOUND, ExceptionConstants.RESOURCE_NOT_FOUND,
					"Role[" + roleId + "] is not found.");
		}

		return role;
	}

}
